using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Infrastructure.CmsDbContext;

namespace JGSY.CMS.LowCode.Platform.Application.Services
{
    /// <summary>
    /// 租户管理服务实现
    /// 提供完整的租户生命周期管理功能
    /// </summary>
    public class TenantService : ITenantService
    {
        private readonly LowCodeDbContext _context;
        private readonly IMemoryCache _cache;
        private readonly ILogger<TenantService> _logger;

        private const string TenantCachePrefix = "tenant:";
        private const string TenantSubdomainCachePrefix = "tenant:subdomain:";
        private const string TenantDomainCachePrefix = "tenant:domain:";
        private static readonly TimeSpan CacheExpiration = TimeSpan.FromMinutes(30);

        public TenantService(
            LowCodeDbContext context,
            IMemoryCache cache,
            ILogger<TenantService> logger)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
            _cache = cache ?? throw new ArgumentNullException(nameof(cache));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        #region 基础CRUD操作

        /// <summary>
        /// 创建新租户
        /// </summary>
        public async Task<Tenant> CreateTenantAsync(CreateTenantRequest request)
        {
            if (request == null) throw new ArgumentNullException(nameof(request));
            if (string.IsNullOrWhiteSpace(request.TenantId)) throw new ArgumentException("租户ID不能为空", nameof(request.TenantId));
            if (string.IsNullOrWhiteSpace(request.Name)) throw new ArgumentException("租户名称不能为空", nameof(request.Name));

            try
            {
                // 验证租户ID唯一性
                var existingTenant = await _context.Tenants
                    .AsNoTracking()
                    .FirstOrDefaultAsync(t => t.TenantId == request.TenantId);

                if (existingTenant != null)
                {
                    throw new InvalidOperationException($"租户ID {request.TenantId} 已存在");
                }

                // 验证子域名唯一性
                if (!string.IsNullOrEmpty(request.SubDomain))
                {
                    var existingSubdomain = await _context.Tenants
                        .AsNoTracking()
                        .FirstOrDefaultAsync(t => t.SubDomain == request.SubDomain);

                    if (existingSubdomain != null)
                    {
                        throw new InvalidOperationException($"子域名 {request.SubDomain} 已被使用");
                    }
                }

                var tenant = new Tenant
                {
                    TenantId = request.TenantId,
                    Name = request.Name,
                    DisplayName = request.DisplayName,
                    Description = request.Description,
                    SubDomain = request.SubDomain,
                    CustomDomain = request.CustomDomain,
                    Status = TenantStatus.Active,
                    SubscriptionPlan = request.SubscriptionPlan,
                    Configuration = request.Configuration,
                    ResourceLimits = request.ResourceLimits,
                    ExpiresAt = request.ExpiresAt,
                    ContactEmail = request.ContactEmail,
                    ContactPhone = request.ContactPhone,
                    TimeZone = request.TimeZone ?? "Asia/Shanghai",
                    Language = request.Language ?? "zh-CN",
                    LogoUrl = request.LogoUrl,
                    ThemeConfiguration = request.ThemeConfiguration,
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };

                _context.Tenants.Add(tenant);
                await _context.SaveChangesAsync();

                _logger.LogInformation("租户创建成功: {TenantId} - {Name}", tenant.TenantId, tenant.Name);
                
                // 预热缓存
                var cacheKey = TenantCachePrefix + tenant.TenantId;
                _cache.Set(cacheKey, tenant, CacheExpiration);

                return tenant;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建租户失败: {TenantId} - {Name}", request.TenantId, request.Name);
                throw;
            }
        }

        /// <summary>
        /// 根据租户ID获取租户
        /// </summary>
        public async Task<Tenant?> GetTenantByIdAsync(string tenantId)
        {
            if (string.IsNullOrWhiteSpace(tenantId)) return null;

            var cacheKey = TenantCachePrefix + tenantId;

            // 尝试从缓存获取
            if (_cache.TryGetValue(cacheKey, out Tenant? cachedTenant))
            {
                _logger.LogDebug("从缓存获取租户: {TenantId}", tenantId);
                return cachedTenant;
            }

            // 从数据库查询
            var tenant = await _context.Tenants
                .AsNoTracking()
                .FirstOrDefaultAsync(t => t.TenantId == tenantId);

            if (tenant != null)
            {
                _cache.Set(cacheKey, tenant, CacheExpiration);
                _logger.LogDebug("从数据库获取租户并缓存: {TenantId}", tenantId);
            }

            return tenant;
        }

        /// <summary>
        /// 获取分页租户列表
        /// </summary>
        public async Task<PagedResult<Tenant>> GetTenantsAsync(GetTenantsRequest request)
        {
            if (request == null) throw new ArgumentNullException(nameof(request));

            var query = _context.Tenants.AsNoTracking().AsQueryable();

            // 搜索过滤
            if (!string.IsNullOrEmpty(request.Search))
            {
                var searchTerm = request.Search.ToLower();
                query = query.Where(t => 
                    (!string.IsNullOrEmpty(t.Name) && t.Name.ToLower().Contains(searchTerm)) ||
                    (!string.IsNullOrEmpty(t.DisplayName) && t.DisplayName.ToLower().Contains(searchTerm)) ||
                    (!string.IsNullOrEmpty(t.TenantId) && t.TenantId.ToLower().Contains(searchTerm)) ||
                    (!string.IsNullOrEmpty(t.SubDomain) && t.SubDomain.ToLower().Contains(searchTerm)));
            }

            // 状态过滤
            if (request.Status.HasValue)
            {
                query = query.Where(t => t.Status == request.Status.Value);
            }

            // 订阅计划过滤
            if (!string.IsNullOrEmpty(request.SubscriptionPlan))
            {
                query = query.Where(t => t.SubscriptionPlan == request.SubscriptionPlan);
            }

            // 排序
            if (!string.IsNullOrEmpty(request.SortBy))
            {
                var isDescending = request.SortDirection?.ToLower() == "desc";
                switch (request.SortBy.ToLower())
                {
                    case "name":
                        query = isDescending ? query.OrderByDescending(t => t.Name) : query.OrderBy(t => t.Name);
                        break;
                    case "status":
                        query = isDescending ? query.OrderByDescending(t => t.Status) : query.OrderBy(t => t.Status);
                        break;
                    case "createdat":
                        query = isDescending ? query.OrderByDescending(t => t.CreatedAt) : query.OrderBy(t => t.CreatedAt);
                        break;
                    case "updatedat":
                        query = isDescending ? query.OrderByDescending(t => t.UpdatedAt) : query.OrderBy(t => t.UpdatedAt);
                        break;
                    default:
                        query = query.OrderByDescending(t => t.CreatedAt);
                        break;
                }
            }
            else
            {
                query = query.OrderByDescending(t => t.CreatedAt);
            }

            var totalCount = await query.CountAsync();
            var tenants = await query
                .Skip(request.Skip)
                .Take(request.PageSize)
                .ToListAsync();

            return new PagedResult<Tenant>(tenants, totalCount, request.PageIndex, request.PageSize);
        }

        /// <summary>
        /// 更新租户信息
        /// </summary>
        public async Task<Tenant> UpdateTenantAsync(string tenantId, UpdateTenantRequest request)
        {
            if (string.IsNullOrWhiteSpace(tenantId)) throw new ArgumentException("租户ID不能为空", nameof(tenantId));
            if (request == null) throw new ArgumentNullException(nameof(request));

            try
            {
                var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.TenantId == tenantId);
                if (tenant == null)
                {
                    throw new ArgumentException($"租户 {tenantId} 不存在");
                }

                // 验证子域名唯一性
                if (!string.IsNullOrEmpty(request.SubDomain) && request.SubDomain != tenant.SubDomain)
                {
                    var existingSubdomain = await _context.Tenants
                        .AsNoTracking()
                        .FirstOrDefaultAsync(t => t.SubDomain == request.SubDomain && t.TenantId != tenantId);

                    if (existingSubdomain != null)
                    {
                        throw new InvalidOperationException($"子域名 {request.SubDomain} 已被使用");
                    }
                }

                // 更新属性（只更新非null值）
                if (!string.IsNullOrEmpty(request.Name)) tenant.Name = request.Name;
                if (request.DisplayName != null) tenant.DisplayName = request.DisplayName;
                if (request.Description != null) tenant.Description = request.Description;
                if (request.SubDomain != null) tenant.SubDomain = request.SubDomain;
                if (request.CustomDomain != null) tenant.CustomDomain = request.CustomDomain;
                if (request.SubscriptionPlan != null) tenant.SubscriptionPlan = request.SubscriptionPlan;
                if (request.Configuration != null) tenant.Configuration = request.Configuration;
                if (request.ResourceLimits != null) tenant.ResourceLimits = request.ResourceLimits;
                if (request.ExpiresAt.HasValue) tenant.ExpiresAt = request.ExpiresAt;
                if (request.ContactEmail != null) tenant.ContactEmail = request.ContactEmail;
                if (request.ContactPhone != null) tenant.ContactPhone = request.ContactPhone;
                if (request.TimeZone != null) tenant.TimeZone = request.TimeZone;
                if (request.Language != null) tenant.Language = request.Language;
                if (request.LogoUrl != null) tenant.LogoUrl = request.LogoUrl;
                if (request.ThemeConfiguration != null) tenant.ThemeConfiguration = request.ThemeConfiguration;

                tenant.UpdatedAt = DateTime.UtcNow;

                await _context.SaveChangesAsync();

                // 清除相关缓存
                ClearTenantCache(tenantId, tenant.SubDomain, tenant.CustomDomain);

                _logger.LogInformation("租户更新成功: {TenantId} - {Name}", tenantId, tenant.Name);
                return tenant;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新租户失败: {TenantId}", tenantId);
                throw;
            }
        }

        /// <summary>
        /// 删除租户（软删除）
        /// </summary>
        public async Task<bool> DeleteTenantAsync(string tenantId)
        {
            if (string.IsNullOrWhiteSpace(tenantId)) return false;

            try
            {
                var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.TenantId == tenantId);
                if (tenant == null) return false;

                // 软删除：设置为非活跃状态
                tenant.Status = TenantStatus.Inactive;
                tenant.UpdatedAt = DateTime.UtcNow;

                await _context.SaveChangesAsync();

                // 清除缓存
                ClearTenantCache(tenantId, tenant.SubDomain, tenant.CustomDomain);

                _logger.LogInformation("租户删除成功: {TenantId} - {Name}", tenantId, tenant.Name);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除租户失败: {TenantId}", tenantId);
                return false;
            }
        }

        #endregion

        #region 查询操作

        /// <summary>
        /// 根据子域名获取租户
        /// </summary>
        public async Task<Tenant?> GetTenantBySubdomainAsync(string subdomain)
        {
            if (string.IsNullOrWhiteSpace(subdomain)) return null;

            var cacheKey = TenantSubdomainCachePrefix + subdomain.ToLower();

            // 尝试从缓存获取
            if (_cache.TryGetValue(cacheKey, out Tenant? cachedTenant))
            {
                return cachedTenant;
            }

            // 从数据库查询
            var tenant = await _context.Tenants
                .AsNoTracking()
                .FirstOrDefaultAsync(t => t.SubDomain == subdomain && t.Status == TenantStatus.Active);

            if (tenant != null)
            {
                _cache.Set(cacheKey, tenant, CacheExpiration);
            }

            return tenant;
        }

        /// <summary>
        /// 根据自定义域名获取租户
        /// </summary>
        public async Task<Tenant?> GetTenantByDomainAsync(string domain)
        {
            if (string.IsNullOrWhiteSpace(domain)) return null;

            var cacheKey = TenantDomainCachePrefix + domain.ToLower();

            // 尝试从缓存获取
            if (_cache.TryGetValue(cacheKey, out Tenant? cachedTenant))
            {
                return cachedTenant;
            }

            // 从数据库查询
            var tenant = await _context.Tenants
                .AsNoTracking()
                .FirstOrDefaultAsync(t => t.CustomDomain == domain && t.Status == TenantStatus.Active);

            if (tenant != null)
            {
                _cache.Set(cacheKey, tenant, CacheExpiration);
            }

            return tenant;
        }

        #endregion

        #region 验证操作

        /// <summary>
        /// 验证租户是否存在且有效
        /// </summary>
        public async Task<bool> ValidateTenantAsync(string tenantId)
        {
            var tenant = await GetTenantByIdAsync(tenantId);
            return tenant != null && 
                   tenant.Status == TenantStatus.Active &&
                   (tenant.ExpiresAt == null || tenant.ExpiresAt > DateTime.UtcNow);
        }

        /// <summary>
        /// 检查租户是否处于活跃状态
        /// </summary>
        public async Task<bool> IsTenantActiveAsync(string tenantId)
        {
            return await ValidateTenantAsync(tenantId);
        }

        /// <summary>
        /// 验证租户域名
        /// </summary>
        public async Task<bool> ValidateTenantDomainAsync(string domain)
        {
            if (string.IsNullOrWhiteSpace(domain)) return false;

            var tenant = await GetTenantByDomainAsync(domain);
            return tenant != null;
        }

        #endregion

        #region 状态管理

        /// <summary>
        /// 激活租户
        /// </summary>
        public async Task<bool> ActivateTenantAsync(string tenantId)
        {
            return await UpdateTenantStatusAsync(tenantId, TenantStatus.Active);
        }

        /// <summary>
        /// 暂停租户
        /// </summary>
        public async Task<bool> SuspendTenantAsync(string tenantId)
        {
            return await UpdateTenantStatusAsync(tenantId, TenantStatus.Suspended);
        }

        private async Task<bool> UpdateTenantStatusAsync(string tenantId, TenantStatus newStatus)
        {
            if (string.IsNullOrWhiteSpace(tenantId)) return false;

            try
            {
                var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.TenantId == tenantId);
                if (tenant == null) return false;

                var oldStatus = tenant.Status;
                tenant.Status = newStatus;
                tenant.UpdatedAt = DateTime.UtcNow;

                await _context.SaveChangesAsync();

                // 清除缓存
                ClearTenantCache(tenantId, tenant.SubDomain, tenant.CustomDomain);

                _logger.LogInformation("租户状态更新: {TenantId} 从 {OldStatus} 变更为 {NewStatus}", 
                    tenantId, oldStatus, newStatus);

                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新租户状态失败: {TenantId} -> {Status}", tenantId, newStatus);
                return false;
            }
        }

        #endregion

        #region 配置管理

        /// <summary>
        /// 获取租户配置
        /// </summary>
        public async Task<string?> GetTenantConfigurationAsync(string tenantId, string key)
        {
            var tenant = await GetTenantByIdAsync(tenantId);
            if (tenant?.Configuration == null) return null;

            try
            {
                // 这里应该解析JSON配置，简化实现直接返回整个配置
                return tenant.Configuration;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "解析租户配置失败: {TenantId} - {Key}", tenantId, key);
                return null;
            }
        }

        /// <summary>
        /// 设置租户配置
        /// </summary>
        public async Task<bool> SetTenantConfigurationAsync(string tenantId, string key, string value)
        {
            try
            {
                var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.TenantId == tenantId);
                if (tenant == null) return false;

                // 简化实现：直接设置配置字符串
                // 实际实现中应该合并JSON配置
                tenant.Configuration = value;
                tenant.UpdatedAt = DateTime.UtcNow;

                await _context.SaveChangesAsync();

                // 清除缓存
                ClearTenantCache(tenantId, tenant.SubDomain, tenant.CustomDomain);

                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "设置租户配置失败: {TenantId} - {Key}", tenantId, key);
                return false;
            }
        }

        #endregion

        #region 资源管理

        /// <summary>
        /// 更新租户资源使用量
        /// </summary>
        public async Task<bool> UpdateTenantResourceUsageAsync(string tenantId, string resourceType, long usage)
        {
            // 这里应该更新资源使用统计表，简化实现返回true
            _logger.LogDebug("更新租户资源使用量: {TenantId} - {ResourceType} - {Usage}", tenantId, resourceType, usage);
            return await Task.FromResult(true);
        }

        /// <summary>
        /// 获取租户资源使用量
        /// </summary>
        public async Task<long> GetTenantResourceUsageAsync(string tenantId, string resourceType)
        {
            // 这里应该从资源使用统计表查询，简化实现返回0
            return await Task.FromResult(0L);
        }

        /// <summary>
        /// 检查租户资源限制
        /// </summary>
        public async Task<bool> CheckTenantResourceLimitAsync(string tenantId, string resourceType, long requestedUsage)
        {
            var tenant = await GetTenantByIdAsync(tenantId);
            if (tenant?.ResourceLimits == null) return true;

            try
            {
                // 这里应该解析ResourceLimits JSON并检查限制
                // 简化实现直接返回true
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "检查租户资源限制失败: {TenantId} - {ResourceType}", tenantId, resourceType);
                return true;
            }
        }

        #endregion

        #region 活动跟踪

        /// <summary>
        /// 记录租户活动
        /// </summary>
        public async Task<bool> RecordTenantActivityAsync(string tenantId)
        {
            try
            {
                var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.TenantId == tenantId);
                if (tenant == null) return false;

                tenant.LastActivityAt = DateTime.UtcNow;
                await _context.SaveChangesAsync();

                // 清除缓存以确保下次查询获取最新活动时间
                var cacheKey = TenantCachePrefix + tenantId;
                _cache.Remove(cacheKey);

                return true;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "记录租户活动失败: {TenantId}", tenantId);
                return false;
            }
        }

        #endregion

        #region 维护操作

        /// <summary>
        /// 获取已过期的租户列表
        /// </summary>
        public async Task<IEnumerable<string>> GetExpiredTenantsAsync()
        {
            var expiredTenants = await _context.Tenants
                .AsNoTracking()
                .Where(t => t.ExpiresAt.HasValue && t.ExpiresAt < DateTime.UtcNow && t.Status == TenantStatus.Active)
                .Select(t => t.TenantId)
                .ToListAsync();

            return expiredTenants;
        }

        /// <summary>
        /// 获取非活跃租户列表
        /// </summary>
        public async Task<IEnumerable<string>> GetInactiveTenantsAsync(TimeSpan inactivityThreshold)
        {
            var cutoffTime = DateTime.UtcNow - inactivityThreshold;
            
            var inactiveTenants = await _context.Tenants
                .AsNoTracking()
                .Where(t => t.Status == TenantStatus.Active && 
                           (t.LastActivityAt == null || t.LastActivityAt < cutoffTime))
                .Select(t => t.TenantId)
                .ToListAsync();

            return inactiveTenants;
        }

        #endregion

        #region 统计信息

        /// <summary>
        /// 获取租户统计信息
        /// </summary>
        public async Task<TenantStatistics> GetTenantStatisticsAsync(string tenantId)
        {
            try
            {
                var tenant = await GetTenantByIdAsync(tenantId);
                if (tenant == null)
                {
                    return new TenantStatistics { LastActivityAt = DateTime.MinValue };
                }

                // 这里应该查询各种统计数据，简化实现
                var statistics = new TenantStatistics
                {
                    UserCount = await _context.Users.CountAsync(u => u.TenantId == tenantId),
                    ArticleCount = await _context.Articles.CountAsync(a => a.TenantId == tenantId),
                    StorageUsage = 0, // 应该计算实际存储使用量
                    LastActivityAt = tenant.LastActivityAt ?? tenant.CreatedAt
                };

                return statistics;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取租户统计信息失败: {TenantId}", tenantId);
                return new TenantStatistics { LastActivityAt = DateTime.MinValue };
            }
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 清除租户相关缓存
        /// </summary>
        private void ClearTenantCache(string tenantId, string? subdomain, string? customDomain)
        {
            // 清除主缓存
            var mainCacheKey = TenantCachePrefix + tenantId;
            _cache.Remove(mainCacheKey);

            // 清除子域名缓存
            if (!string.IsNullOrEmpty(subdomain))
            {
                var subdomainCacheKey = TenantSubdomainCachePrefix + subdomain.ToLower();
                _cache.Remove(subdomainCacheKey);
            }

            // 清除自定义域名缓存
            if (!string.IsNullOrEmpty(customDomain))
            {
                var domainCacheKey = TenantDomainCachePrefix + customDomain.ToLower();
                _cache.Remove(domainCacheKey);
            }

            _logger.LogDebug("清除租户缓存: {TenantId}", tenantId);
        }

        #endregion
    }
}
